package com.whale.cloud.util.rest.dataengine;

import com.alibaba.fastjson.JSONObject;
import com.whale.cloud.util.StringUtils;
import com.whale.cloud.util.rest.condition.ELogic;
import lombok.extern.log4j.Log4j2;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/** Created by paco on 1/6/2017. */
@Log4j2
public class OrganizeQuery {
  private String condition = null;
  private JSONObject fractionCondition = new JSONObject();

  private OrganizeQuery() {
    //exp=new LogicExpression();
  }

  public static OrganizeQuery getInstance() {
    return new OrganizeQuery();
  }

  public LogicExpression setCondition(String condition) {
    this.condition = condition;
    return extractCondition();
  }

  /**
   * 原字符串：NOT FR_ACTIVE:N AND CORP_ID:C10222 AND (((T_CR_Y:2017 AND T_CR_M:04 AND T_CR_D:[28 TO 31]
   * ) OR (T_CR_Y:2017 AND T_CR_M:05 AND T_CR_D:[01 TO 16] )) AND AMT_TRADE_3:[3000 TO 5000]) and
   * CORP_ID:C10222 AND (((T_CR_Y:2017 AND T_CR_M:04 AND T_CR_D:[28 TO 32] ) OR (T_CR_Y:2017 AND
   * T_CR_M:05 AND T_CR_D:[01 TO 16] )) AND AMT_TRADE_3:[3001 TO 5000]) 提取过程： 1、<<0>>=T_CR_Y:2017
   * AND T_CR_M:04 AND T_CR_D:[28 TO 31] tre:NOT FR_ACTIVE:N AND CORP_ID:C10222 AND ((<<0>> OR
   * (T_CR_Y:2017 AND T_CR_M:05 AND T_CR_D:[01 TO 16] )) AND AMT_TRADE_3:[3000 TO 5000]) and
   * CORP_ID:C10222 AND (((T_CR_Y:2017 AND T_CR_M:04 AND T_CR_D:[28 TO 32] ) OR (T_CR_Y:2017 AND
   * T_CR_M:05 AND T_CR_D:[01 TO 16] )) AND AMT_TRADE_3:[3001 TO 5000]) 2、<<1>>=T_CR_Y:2017 AND
   * T_CR_M:05 AND T_CR_D:[01 TO 16] tre:NOT FR_ACTIVE:N AND CORP_ID:C10222 AND ((<<0>> OR <<1>>)
   * AND AMT_TRADE_3:[3000 TO 5000]) and CORP_ID:C10222 AND (((T_CR_Y:2017 AND T_CR_M:04 AND
   * T_CR_D:[28 TO 32] ) OR <<1>>) AND AMT_TRADE_3:[3001 TO 5000]) 3、<<2>>=<<0>> OR <<1>> tre:NOT
   * FR_ACTIVE:N AND CORP_ID:C10222 AND (<<2>> AND AMT_TRADE_3:[3000 TO 5000]) and CORP_ID:C10222
   * AND (((T_CR_Y:2017 AND T_CR_M:04 AND T_CR_D:[28 TO 32] ) OR <<1>>) AND AMT_TRADE_3:[3001 TO
   * 5000]) 4、<<3>>=<<2>> AND AMT_TRADE_3:[3000 TO 5000] tre:NOT FR_ACTIVE:N AND CORP_ID:C10222 AND
   * <<3>> and CORP_ID:C10222 AND (((T_CR_Y:2017 AND T_CR_M:04 AND T_CR_D:[28 TO 32] ) OR <<1>>) AND
   * AMT_TRADE_3:[3001 TO 5000]) 5、<<4>>=T_CR_Y:2017 AND T_CR_M:04 AND T_CR_D:[28 TO 32] tre:NOT
   * FR_ACTIVE:N AND CORP_ID:C10222 AND <<3>> and CORP_ID:C10222 AND ((<<4>> OR <<1>>) AND
   * AMT_TRADE_3:[3001 TO 5000]) 6、<<5>>=<<4>> OR <<1>> tre:NOT FR_ACTIVE:N AND CORP_ID:C10222 AND
   * <<3>> and CORP_ID:C10222 AND (<<5>> AND AMT_TRADE_3:[3001 TO 5000]) 7、<<6>>=<<5>> AND
   * AMT_TRADE_3:[3001 TO 5000] tre:NOT FR_ACTIVE:N AND CORP_ID:C10222 AND <<3>> and CORP_ID:C10222
   * AND <<6>>
   *
   * <p>提取结果：NOT FR_ACTIVE:N AND CORP_ID:C10222 AND <<3>> and CORP_ID:C10222 AND <<6>>
   *
   * @return
   */
  private LogicExpression extractCondition() {
    if (StringUtils.isNull(this.condition)) {
      return null;
    }
    String tempCondition = this.condition;

    tempCondition = tempCondition.replaceAll("(?<=\\s*\\(\\s*\\*[^\\)]+)\\)", "§r§");
    tempCondition = tempCondition.replaceAll("(?<=:)\\s*\\(\\s*\\*\\s*", "§l§");
    Pattern pp = Pattern.compile("(?<=\\((?=[^\\(\\)]+\\)))[^\\(\\)]+(?=\\))"); //(?<!\\\\)
    Matcher mm = pp.matcher(tempCondition);
    int ecount = -1;
    String fString = "";
    while (mm.find()) {
      mm = pp.matcher(tempCondition);
      while (mm.find()) {
        ecount++;
        fString = mm.group();
        fractionCondition.put("<<" + ecount + ">>", fString);
        tempCondition = tempCondition.replace("(" + fString + ")", "<<" + ecount + ">>");
        mm = pp.matcher(tempCondition);
      }
    }
    this.condition = tempCondition;
    return buildExpression(this.condition, ELogic.and);
  }

  public LogicExpression buildExpression(String extractCondition, ELogic el) {
    String splitChar = "";
    if (el == ELogic.and) {
      splitChar = "\\s+(AND|and|&&|&)\\s+";
    } else if (el == ELogic.or) {
      splitChar = "\\s+(OR|or|\\|\\||\\|)\\s+";
    }
    if (StringUtils.isNull(extractCondition)) {
      return null;
    }
    String[] cs = extractCondition.split(splitChar);

    int elength = cs.length;
    String tempCondition;
    LogicExpression exp = null;
    Pattern pp = null;
    Matcher mm = null;
    for (int i = 0; i < elength; i++) {
      tempCondition = cs[i];
      if (StringUtils.isNull(tempCondition)) {
        log.error("condition has null Express: " + extractCondition);
        continue;
      }

      //1、判断条件中是否包含逻辑(或)运算符
      pp = Pattern.compile("\\s+(OR|or|\\|\\||\\|)\\s+"); //(?<!\\\\)
      mm = pp.matcher(tempCondition);
      if (mm.find()) {
        LogicExpression temple = buildExpression(tempCondition, ELogic.or);
        if (exp == null) {
          exp = temple;
        } else {
          exp.addLogicExpression(temple, el);
        }
        //else{exp.combine(temple,el);}
        continue;
      }

      //2、判断是否包含子表达式，格式：<<\\d+>>
      pp = Pattern.compile("\\s*<<\\d+>>\\s*");
      mm = pp.matcher(tempCondition);
      if (mm.find()) {
        if (exp == null) {
          exp = new LogicExpression();
        }
        LogicExpression temple =
            buildExpression(fractionCondition.getString(tempCondition.trim()), ELogic.and);
        exp = exp.combine(temple, el);
        exp.setEl(el);
        continue;
      }

      //3、正常情况
      if (exp == null) {
        exp = new LogicExpression(tempCondition, el);
      } else {
        exp = exp.combine(new LogicExpression(tempCondition, el), el);
      }
    }
    return exp;
  }
}
